home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
New Star Software Collection
/
NSS_Collection.iso
/
3-170 dbase 10 for windows
/
1.ima
/
DOC.PAK
/
DLL_API.TXT
< prev
next >
Wrap
Text File
|
1993-07-26
|
12KB
|
332 lines
Copyright (c) 1991-1993 Borland International, Inc.
All Rights Reserved.
CALLING DLL FUNCTIONS AND THE WINDOWS API
-----------------------------------------
Dynamic-link libraries (DLLs) are files containing compiled
program code that Windows applications load and execute at
runtime. Through DLLs, your Bladerunner application can call
non-dBASE functions, such as C and Pascal functions.
The Windows API (application programming interface) is a library
of C functions contained in DLLs. This document introduces
dynamic linking to dBASE programmers and shows how to call non-
dBASE functions from DLLs and the Windows API.
Contents
--------
I. About Libraries and Linking
II. Calling DLL Functions
III. Calling Windows API Functions
About Libraries and Linking
---------------------------
The terms "library" and "linking" mean different things to
different programmers. dBASE III PLUS developers maintain
libraries of often-used routines and incorporate them into
applications without linking. dBASE IV developers use
DBLINK to link compiled programs and library routines into
one large object file.
C language developers perform "static linking" when they
create an executable file from various object modules and
run-time libraries. Static linking occurs just once at the
time you create an application. In contrast, Windows
applications perform "dynamic linking" by calling routines
and resources at run time. Dynamic linking occurs many
times while an application is running. Since DLLs are parts
of applications, they must be present on the disk when a
program calls one of their routines or resources.
By maintaining compiled routines and resources in separate
files, and linking them to applications at run time:
o You can share the same library among many applications,
even among two applications running concurrently in
Windows 386 enhanced mode.
o You don't have to recompile or relink the library every
time you build your application.
o You create smaller executable files.
Calling DLL Functions
---------------------
Using DLLs is much like using procedure files. You load a DLL
into memory before using one of its routines, then release the
DLL when its routines are no longer needed. If the DLL file has
a .DLL extension, or is part of the WIndows API, Bladerunner loads
the file automatically; otherwise you need to explicitly load the
file with LOAD DLL. (LOAD DLL is not implemented in this Alpha
release; you can use the Windows API function LoadLibrary()
instead.)
Since DLLs are loaded at runtime, DLL files must be present on disk
at runtime.
You need to declare a "prototype" for each non-dBASE function
before you call the function. A prototype specifies the data
type for the function's parameters and return value. You declare
prototypes with the EXTERN command.
The need for prototypes becomes apparent when you consider
the problem of passing parameters into functions of
different languages. Bladerunner uses prototypes to
convert the data types of parameters and return values
automatically. For instance, when you call a C function,
Bladerunner automatically converts the parameters from
dBASE data types into C data types, and then converts the
return values from C back into dBASE.
Follow these steps to call DLL functions:
1. If the DLL file does not have a .DLL extension, and is not part
of the Windows API, you need to load the DLL file into memory with
LOAD DLL. (Note: In this Alpha release, LOAD DLL is not yet
implemented. You can use the Windows API function LoadLibrary()
instead.)
If the DLL file has a .DLL extension, you can skip this step.
2. Prototype the non-dBASE functions with EXTERN.
3. Call the non-dBASE functions right in your dBASE code.
4. Remove the DLL file from memory with RELEASE DLL.
EXTERN prototypes non-dBASE functions. Here is the syntax:
EXTERN [CDECL] <cType1> <function name> ([<cType2>, ...])<dll name>
These are the options for EXTERN:
[CDECL] -- Tells dBASE to use the C language calling convention,
instead of the default Pascal calling convention, so you can pass
additional parameters beyond those specified in the declaration
for this function.
<cType1> -- Specifies the return value's data type. All EXTERN
functions have to specify a return type even if it is CVOID.
<cType2> -- Optionally specifies the data type of each parameter.
All arguments need to match their declared type as follows:
Data Type Keyword API Data Type
--------- ------- -------------
Numeric CWORD unsigned int (16 bit)
Numeric CLONG unsigned long (32 bit)
Numeric CDOUBLE double float (64 bit double)
Character CPTR char far * (string)
N/A CVOID void
<function name> -- The name of the function in the DLL.
<dll name> -- The name of the Windows .DLL that contains the
function.
Note: Most of the functionality of Windows is contained in DLL's,
but dynamic link library code can also be present in .EXE files
(or even in .DRV or .FON files).
Example:
EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
Calling Windows API Functions
-----------------------------
The API function must be prototyped before you call it from
Bladerunner. You can prototype the API functions at the Command
window, in the .PRG, or in an #include file. Once an API
function has been prototyped, it is available as if it were an
internal Bladerunner function, until you end that Bladerunner
session.
Execute the API function like any dBASE function after you have
prototyped it. API functions can be called directly or they can
be part of a dBASE expression or function. Also, dBASE functions
can be put inside API functions.
Example:
EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
? MessageBox(0,"My Text","From Windows",17)
or
pressed = MessageBox(0,"My Text","From Windows",17)
or
? MessageBox(0,"My Text","From Windows",HTOI("00011"))
This displays a Windows MessageBox in the middle of the screen,
with the Title: "From Windows" and the Message: "My Text" and two
buttons: "OK" "CANCEL" and the ICON: "STOP". It returns the
value for the button pressed 1= OK , 2 = CANCEL.
Note: You can execute the function without the ? (print) command,
just by putting the function name with its arguments on the
command line by itself, but you won't display the return value.
Example:
EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
MessageBox(0,"My Text","From Windows",17)
Displays MessageBox as above but without displaying the return
value for the button pressed.
The windows API functions can be prototyped and executed right at
the command window in Bladerunner. You do not have to load any
special header file or .DLL to access the windows API functions.
API Window Handles
API window handles are numbers, 16 bit integers (CWORD), like
file handles in DOS, that are assigned to every window. To get
the Windows handle of dBASEWIN.EXE you can use the following
approaches:
Example A:
hDBW = _APP.FRAMEWIN.HWND
The variable hDBW now holds the Windows handle to dBASEWIN.EXE
FRAMEWIN (the main window of dBASEWIN.EXE).
Example B:
EXTERN CWORD GetActiveWindow( ) user.exe
hDBW = GetActiveWindow( )
The variable hDBW now holds the windows handle of the active
window. If you type the above in the Command window, the
variable hDBW will hold the Windows handle of the FRAMEWIN of
dBASEWIN.EXE, as in Example A, above.
Example C:
EXTERN CWORD GetFocus() user.exe
hDBW = GetFocus()
The variable hDBW now holds the windows handle of the window with
input focus. If you type the above in the Command window, the
variable hDBW will hold the Windows handle of the Command window.
But if you DEFINE a window and ACTIVATE the window, then issue
the GetFocus() function in your program, it will return the
handle of the window you ACTIVATED.
Windows API Constants
Windows has many constants defined as integers, like the cursors
below.
Example:
#define IDC_ARROW (32512)
#define IDC_IBEAM (32513)
#define IDC_WAIT (32514)
#define IDC_CROSS (32515)
#define IDC_UPARROW (32516)
#define IDC_SIZE (32640)
#define IDC_ICON (32641)
#define IDC_SIZENWSE (32642)
#define IDC_SIZENESW (32643)
#define IDC_SIZEWE (32644)
#define IDC_SIZENS (32645)
EXTERN CWORD LoadCursor(CWORD,CWORD) user.exe
EXTERN CWORD SetCursor(CWORD) user.exe
orgcsr = SetCursor(LoadCursor(0, IDC_ICON))
FOR x = 1 to 210000
NEXT
SetCursor(orgcsr)
HEX Numbers
Windows has many constants defined as hex numbers.
Example:
#define MB_OK 0x0000
#define MB_OKCANCEL 0x0001
#define MB_ABORTRETRYIGNORE 0x0002
#define MB_YESNOCANCEL 0x0003
#define MB_ICONHAND 0x0010
#define MB_ICONQUESTION 0x0020
#define MB_ICONEXCLAMATION 0x0030
#define MB_ICONASTERISK 0x0040
EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
MessageBox(0,"My Text","From Windows",HTOI("0x0022"))
The dBASE functions for working with hex numbers are:
HTOI() Takes a hex number as a string and returns an
integer.
ITOH() Takes an integer and returns a hex number as a
string.
Bits
Many DLL functions interpret individual bits in an integer
argument or return value. We have added several new functions to
Bladerunner for working with bits. Bits are numbered in an
integer from the least significant bit (rightmost) to the most
significant bit (leftmost). Bit numbering starts at 0 (see
example below).
Most Least
Significant Significant
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Example:
* gVer.prg
#define HiWord(x) (bitrshift(bitand(x,4294901760),16))
#define LoWord(x) (bitand(x,65535))
#define HiByte(x) (ltrim(str(bitrshift(bitand(x,65280),8))))
#define LoByte(x) (ltrim(str(bitand(x,255))))
EXTERN CLONG GetVersion( ) krnl386.exe
z=GetVersion( )
RETURN "DOS version;
"+HiByte(HiWord(z))+"."+LoByte(HiWord(z))+ ;
", Windows version"+LoByte(LoWord(z))+"."+HiByte(LoWord(z))
Note: The above code example, and several others, are included
with the sample code provided with this Alpha release.
The new dBASE bit functions are: BitAND(), BitLshift(),
BitRshift(), BitOr(), BitXor(),and BitSet().
Windows API Strings
Many API functions take a string as an argument. Some API
functions only want a Pointer (a reference) to a string that the
function can fill with the returned information. In this case
you need to make the string large enough to hold the result (some
also require you to pass the length of the string as a argument).
Example:
dBWhand = _APP.FRAMEWIN.HWND
EXTERN CWORD GetWindowText(CWORD,CPTR,CWORD) user.exe
winTitle = SPACE(80)
&& first make empty string to be filled
lenTitle = GetWindowText(dBWhand,winTitle,80)
? winTitle
Note: With Bladerunner's object-oriented language extensions you
can get the same information with this command:
? _APP.FRAMEWIN.CAPTION